- Utility/SD新增
- 等待店家確認訂單 -> 店家確認後改為訂單準備中 -> 店家準備完成後改為訂單完成、可取貨-> 使用者取貨後改為訂單完成
public const string StatusPending = "Pending"; // 等待店家確認訂單
public const string StatusInProcess = "Processing"; // 店家確認後改為訂單準備中
public const string StatusCancelled = "Cancelled"; // 店家或顧客取消訂單
public const string StatusReady = "Ready"; // 店家準備完成,顧客可以取貨
public const string StatusCompleted = "Completed"; // 顧客取貨及付款後,店家結束訂單
[HttpPost]
[ActionName("Summary")]
public IActionResult SummaryPOST(ShoppingCartVM shoppingCartVM)
{
var claimsIdentity = (ClaimsIdentity)User.Identity;
var userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
ShoppingCartVM.ShoppingCartList = _unitOfWork.ShoppingCart.GetAll(u => u.ApplicationUserId == userId, includeProperties: "Product");
ShoppingCartVM.OrderHeader.OrderDate = System.DateTime.Now;
ShoppingCartVM.OrderHeader.ApplicationUserId = userId;
ShoppingCartVM.OrderHeader.ApplicationUser = _unitOfWork.ApplicationUser.Get(u => u.Id == userId);
foreach (var cart in ShoppingCartVM.ShoppingCartList)
{
ShoppingCartVM.OrderHeader.OrderTotal += (cart.Product.Price * cart.Count);
}
_unitOfWork.OrderHeader.Add(ShoppingCartVM.OrderHeader);
_unitOfWork.Save();
foreach (var cart in ShoppingCartVM.ShoppingCartList)
{
OrderDetail orderDetail = new()
{
ProductId = cart.ProductId,
OrderHeaderId = ShoppingCartVM.OrderHeader.Id,
Color = cart.Color,
Size = cart.Size,
Price = cart.Product.Price,
Count = cart.Count
};
_unitOfWork.OrderDetail.Add(orderDetail);
_unitOfWork.Save();
}
return RedirectToAction(nameof(OrderConfirmation), new { id = ShoppingCartVM.OrderHeader.Id });
}
public IActionResult OrderConfirmation(int id)
{
OrderHeader orderHeader = _unitOfWork.OrderHeader.Get(u => u.Id == id, includeProperties: "ApplicationUser");
_unitOfWork.OrderHeader.UpdateStatus(id, SD.StatusPending);
List<ShoppingCart> shoppingCarts = _unitOfWork.ShoppingCart.GetAll(u => u.ApplicationUserId == orderHeader.ApplicationUserId).ToList();
_unitOfWork.ShoppingCart.RemoveRange(shoppingCarts);
_unitOfWork.Save();
return View(id);
}
- 新增Order確認View
- 對OrderConfirmation右鍵新增View
@model int
<div class="container row pt-4">
<div class="col-12 text-center">
<h1 class="text-primary text-center">訂單送出成功</h1>
您的訂單編號為 : @Model <br /><br />
</div>
<div class="col-12 text-center" style="color:maroon">
<br />
您的訂單已成功下達! <br />
</div>
</div>
- 修改訂單狀態
- IOrderHeaderRepository新增:
void UpdateStatus(int id, string orderStatus, string? paymentStatus = null);
- OrderHeaderRepository的Update下方新增:
public void UpdateStatus(int id, string orderStatus, string? paymentStatus = null)
{
var orderFromDb = _db.OrderHeaders.FirstOrDefault(u => u.Id == id);
if (orderFromDb != null)
{
orderFromDb.OrderStatus = orderStatus;
if (!string.IsNullOrEmpty(paymentStatus))
{
orderFromDb.PaymentStatus = paymentStatus;
}
}
}
- 訂單管理
- Admin新增OrderController
- 設定管理者與員工可以看到所有訂單,其餘人只能看到自己的訂單
[Area("Admin")]
[Authorize]
public class OrderController : Controller
{
private readonly IUnitOfWork _unitOfWork;
[BindProperty]
public OrderVM OrderVM { get; set; }
public OrderController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IActionResult Index(string status)
{
IEnumerable<OrderHeader> objOrderHeaders;
if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
{
objOrderHeaders = _unitOfWork.OrderHeader.GetAll(includeProperties: "ApplicationUser").ToList();
}
else
{
var claimsIdentity = (ClaimsIdentity)User.Identity;
var userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
objOrderHeaders = _unitOfWork.OrderHeader
.GetAll(u => u.ApplicationUserId == userId, includeProperties: "ApplicationUser");
}
switch (status)
{
case "Pending":
objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusPending);
break;
case "Processing":
objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusInProcess);
break;
case "Ready":
objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusReady);
break;
case "Completed":
objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusCompleted);
break;
default:
break;
}
return View(objOrderHeaders);
}
}
public class OrderVM
{
public OrderHeader OrderHeader { get; set; }
public IEnumerable<OrderDetail> OrderDetail { get; set; }
}
@model IEnumerable<ClothShop.Models.OrderHeader>
@{
var status = Context.Request.Query["status"];
var pending = "text-primary";
var processing = "text-primary";
var ready = "text-primary";
var completed = "text-primary";
var all = "text-primary";
switch (status)
{
case "Pending":
pending = "active text-white";
break;
case "Processing":
processing = "active text-white";
break;
case "Ready":
ready = "active text-white";
break;
case "Completed":
completed = "active text-white";
break;
default:
all = "active text-white";
break;
}
}
<div class="p-3">
<div class="d-flex justify-content-between pt-4">
<div class="pt-2">
<h2 class="text-primary">訂單清單 Order List</h2>
</div>
<div class="p-2">
<ul class="list-group list-group-horizontal-sm">
<a style="text-decoration:none;" asp-controller="Order"
asp-action="Index" asp-route-status="Pending">
<li class="list-group-item" @pending>等待確認訂單</li>
</a>
<a style="text-decoration:none;" asp-controller="Order"
asp-action="Index" asp-route-status="Processing">
<li class="list-group-item" @processing>訂單準備中</li>
</a>
<a style="text-decoration:none;" asp-controller="Order"
asp-action="Index" asp-route-status="Ready">
<li class="list-group-item" @ready>可取貨</li>
</a>
<a style="text-decoration:none;" asp-controller="Order"
asp-action="Index" asp-route-status="Completed">
<li class="list-group-item" @completed>已完成</li>
</a>
<a style="text-decoration:none;" asp-controller="Order"
asp-action="Index" asp-route-status="all">
<li class="list-group-item" @all>全部訂單</li>
</a>
</ul>
</div>
</div>
<table id="tblData" class="table table-bordered table-striped" style="width:100%">
<thead>
<tr class="align-middle">
<th>訂單編號</th>
<th>姓名</th>
<th>電話號碼</th>
<th>信箱</th>
<th>訂單狀態</th>
<th>總計金額</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.Id)</td>
<td>@Html.DisplayFor(modelItem => item.Name)</td>
<td>@Html.DisplayFor(modelItem => item.PhoneNumber)</td>
<td>@Html.DisplayFor(modelItem => item.ApplicationUser.Email)</td>
<td>@Html.DisplayFor(modelItem => item.OrderStatus)</td>
<td>@Html.DisplayFor(modelItem => item.OrderTotal)</td>
<td>
<div class="w-75 btn-group" role="group">
<a href="/admin/order/details?orderId=${data}" class="btn btn-primary mx-2"> Edit</a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
@section Scripts {
}
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Admin" asp-controller="Order" asp-action="Index">訂單</a>
</li>
public IActionResult Details(int orderId)
{
OrderVM = new OrderVM
{
OrderHeader = _unitOfWork.OrderHeader.Get(u => u.Id == orderId, includeProperties: "ApplicationUser"),
OrderDetail = _unitOfWork.OrderDetail.GetAll(u => u.OrderHeaderId == orderId, includeProperties: "Product")
};
return View(OrderVM);
}
[HttpPost]
[Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
public IActionResult UpdateOrderDetail()
{
var orderHeaderFromDb = _unitOfWork.OrderHeader.Get(u => u.Id == OrderVM.OrderHeader.Id);
orderHeaderFromDb.Name = OrderVM.OrderHeader.Name;
orderHeaderFromDb.PhoneNumber = OrderVM.OrderHeader.PhoneNumber;
orderHeaderFromDb.Address = OrderVM.OrderHeader.Address;
_unitOfWork.OrderHeader.Update(orderHeaderFromDb);
_unitOfWork.Save();
return RedirectToAction(nameof(Details), new { orderId = orderHeaderFromDb.Id });
}
@model OrderVM
@using ClothShop.Utility
<form method="post">
<input asp-for="OrderHeader.Id" hidden />
<br />
<div class="container">
<div class="card">
<div class="card-header bg-dark text-light ml-0">
<div class="container row">
<div class="col-12 d-none d-md-block col-md-6 p-2">
<i class="fas fa-shopping-cart"></i> 訂單總計 Order Summary
</div>
<div class="col-12 col-md-4 offset-md-2 text-right p-2">
<a asp-action="Index" class="btn btn-outline-info form-control btn-sm">回訂單列 Back to Orders</a>
</div>
</div>
</div>
<div class="card-body">
<div class="container rounded p-2">
<div class="row">
<div class="col-12 col-lg-6 pb-4">
<div class="row">
<h4 class="d-flex justify-content-between align-items-center mb-3">
<span class="text-primary">訂購人資訊 PickUp Details:</span>
</h4>
</div>
<div class="row my-1">
<div class="col-4">姓名 Name</div>
<div class="col-8">
@if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
{
<input asp-for="OrderHeader.Name" type="text" class="form-control" />
<span asp-validation-for="OrderHeader.Name" class="text-danger"></span>
}
else
{
<input asp-for="OrderHeader.Name" readonly type="text" class="form-control" />
}
</div>
</div>
<div class="row my-1">
<div class="col-4">手機 Phone</div>
<div class="col-8">
@if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
{
<input asp-for="OrderHeader.PhoneNumber" type="text" class="form-control" />
<span asp-validation-for="OrderHeader.PhoneNumber" class="text-danger"></span>
}
else
{
<input asp-for="OrderHeader.PhoneNumber" readonly type="text" class="form-control" />
}
</div>
</div>
<div class="row my-1">
<div class="col-4">地址 Address</div>
<div class="col-8">
@if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
{
<input asp-for="OrderHeader.Address" type="text" class="form-control" />
<span asp-validation-for="OrderHeader.Address" class="text-danger"></span>
}
else
{
<input asp-for="OrderHeader.Address" readonly type="text" class="form-control" />
}
</div>
</div>
<div class="row my-1">
<div class="col-4">信箱 Email</div>
<div class="col-8">
<input asp-for="OrderHeader.ApplicationUser.Email" readonly type="text" class="form-control" />
</div>
</div>
<div class="row my-1">
<div class="col-4">訂購日期 Order Date</div>
<div class="col-8">
<input value="@Model.OrderHeader.OrderDate.ToShortDateString()" type="text" class="form-control" readonly />
</div>
</div>
@if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
{
<button type="submit" asp-action="UpdateOrderDetail" class="btn btn-warning form-control my-1">修改訂單資訊 Update Order Details</button>
}
</div>
<div class="col-12 col-lg-5 offset-lg-1">
<h4 class="d-flex justify-content-between align-items-center mb-3">
<span class="text-primary">訂購內容 Order Summary</span>
</h4>
<label class="btn btn-outline-primary form-control my-2">訂單狀態 Order Status - @Model.OrderHeader.OrderStatus</label>
<ul class="list-group mb-3">
@foreach (var detail in Model.OrderDetail)
{
<li class="list-group-item d-flex justify-content-between p-2">
<div class="row container">
<div class="col-8">
<h6 class="my-0 text-primary">@detail.Product.Name</h6>
<small class="text-muted">價格:@detail.Price.ToString("c")</small><br />
<small class="text-muted">數量:@detail.Count</small><br />
<small class="text-muted">顏色:@detail.Color</small><br />
<small class="text-muted">尺寸:@detail.Size</small>
</div>
<div class="col-4">
<p class="text-success"> @((detail.Count * detail.Price).ToString("c"))</p>
</div>
</div>
</li>
}
<li class="list-group-item bg-info">
<div class="row container">
<div class="col-6 text-center">
<h5 class="text-white">總計 TOTAL </h5>
</div>
<div class="col-6 text-center">
<h5 class="text-white">@Model.OrderHeader.OrderTotal.ToString("c")</h5>
</div>
</div>
</li>
</ul>
@if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
{
@if (Model.OrderHeader.OrderStatus == SD.StatusPending)
{
<button type="submit" asp-action="StartProcessing" class="btn btn-primary form-control my-1">接受訂單</button>
}
@if (Model.OrderHeader.OrderStatus == SD.StatusInProcess)
{
<button type="submit" asp-action="OrderReady" class="btn btn-primary form-control my-1">製作完成(通知顧客取貨)</button>
}
@if (Model.OrderHeader.OrderStatus == SD.StatusReady)
{
<button type="submit" asp-action="OrderCompleted" class="btn btn-success form-control my-1">確認付款(訂單完成)</button>
}
@if (Model.OrderHeader.OrderStatus != SD.StatusCompleted && Model.OrderHeader.OrderStatus != SD.StatusCancelled)
{
<button type="submit" asp-action="CancelOrder" class="btn btn-danger form-control my-1">取消訂單</button>
}
}
</div>
</div>
</div>
</div>
</div>
</div>
</form>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
- OrderController 新增接收訂單 / 準備完成 / 訂單完成 / 訂單取消 (四個)Action
[HttpPost]
[Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
public IActionResult StartProcessing()
{
_unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusInProcess);
_unitOfWork.Save();
return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
}
[HttpPost]
[Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
public IActionResult OrderReady()
{
_unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusReady);
_unitOfWork.Save();
return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
}
[HttpPost]
[Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
public IActionResult OrderCompleted()
{
_unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusCompleted);
_unitOfWork.Save();
return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
}
[HttpPost]
[Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
public IActionResult CancelOrder()
{
_unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusCancelled);
_unitOfWork.Save();
return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
}